﻿using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using System.Windows.Media;
using System.Windows.Navigation;
using System.Xml;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;

namespace CuteRibs.MVVMLib
{
	public class AppBase : Application
	{
		public static string AppName { get; private set; }
		public static string Version { get; private set; }
		public static bool IsDesignMode { get { return DesignerProperties.IsInDesignTool; } }

		public PhoneApplicationFrame RootFrame { get; protected set; }
		protected bool PhoneApplicationInitialized = false;
		protected bool IsErrorAlertEnabled { get; set; }


		#region system resources

		private static Color phoneForegroundColor;
		private static Color phoneBackgroundColor;
		private static Color phoneAccentColor;
		private static Brush phoneForegroundBrush;
		private static Brush phoneBackgroundBrush;
		private static Brush phoneAccentBrush;

		public static Color PhoneForegroundColor
		{
			get
			{
				if (phoneForegroundColor == default(Color))
				{
					phoneForegroundColor = (Color)Application.Current.Resources["PhoneForegroundColor"];
				}

				return phoneForegroundColor;
			}
		}

		public static Color PhoneBackgroundColor
		{
			get
			{
				if (phoneBackgroundColor == default(Color))
				{
					phoneBackgroundColor = (Color)Application.Current.Resources["PhoneBackgroundColor"];
				}

				return phoneBackgroundColor;
			}
		}

		public static Color PhoneAccentColor
		{
			get
			{
				if (phoneAccentColor == default(Color))
				{
					phoneAccentColor = (Color)Application.Current.Resources["PhoneAccentColor"];
				}

				return phoneAccentColor;
			}
		}

		public static Brush PhoneForegroundBrush
		{
			get
			{
				if (phoneForegroundBrush == null)
				{
					phoneForegroundBrush = Application.Current.Resources["PhoneForegroundBrush"] as Brush;
				}

				return phoneForegroundBrush;
			}
		}

		public static Brush PhoneBackgroundBrush
		{
			get
			{
				if (phoneBackgroundBrush == null)
				{
					phoneBackgroundBrush = Application.Current.Resources["PhoneBackgroundBrush"] as Brush;
				}

				return phoneBackgroundBrush;
			}
		}

		public static Brush PhoneAccentBrush
		{
			get
			{
				if (phoneAccentBrush == null)
				{
					phoneAccentBrush = Application.Current.Resources["PhoneAccentBrush"] as Brush;
				}

				return phoneAccentBrush;
			}
		}
		#endregion

		public AppBase()
		{
			PhoneApplicationService service = new PhoneApplicationService();
			service.Launching += (s, e) => this.OnAppLaunching(e);
			service.Closing += (s, e) => this.OnAppClosing(e);
			service.Deactivated += (s, e) => this.OnAppDeactivated(e);
			service.Activated += (s, e) => this.OnAppActivated(e);
			this.UnhandledException += (s, e) => this.OnUnhandledException(e);

			AppName = GetAppAttribute("Title");
			Version = GetAppAttribute("Version");
			this.ApplicationLifetimeObjects.Add(service);
			this.InitializePhoneApplication(null);

			if (Debugger.IsAttached)
			{
				Application.Current.Host.Settings.EnableFrameRateCounter = true;
				PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Disabled;
			}
		}

		#region lifetime events

		protected virtual void OnAppLaunching(LaunchingEventArgs e) { }

		protected virtual void OnAppClosing(ClosingEventArgs e) { }

		protected virtual void OnAppDeactivated(DeactivatedEventArgs e) { }

		protected virtual void OnAppActivated(ActivatedEventArgs e) { }

		#endregion

		protected virtual void OnUnhandledException(ApplicationUnhandledExceptionEventArgs e)
		{
			if (this.IsErrorAlertEnabled)
			{
				MessageBox.Show(e.ExceptionObject.Message);
			}

			//if (Debugger.IsAttached)
			//{
			//    Debugger.Break();
			//}
		}

		#region Phone application initialization

		protected virtual void InitializePhoneApplication(PhoneApplicationFrame frame)
		{
			if (this.PhoneApplicationInitialized)
			{
				return;
			}

			this.RootFrame = frame ?? new TransitionFrame();
			this.RootFrame.Navigated += this.CompleteInitializePhoneApplication;
			this.RootFrame.NavigationFailed += (s, e) => this.OnRootFrameNavigationFailed(e);
			this.PhoneApplicationInitialized = true;
		}

		private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e)
		{
			if (this.RootVisual != this.RootFrame)
			{
				this.RootVisual = this.RootFrame;
			}

			this.RootFrame.Navigated -= CompleteInitializePhoneApplication;
			this.OnCompleteInitializePhoneApplication(e);
		}

		protected virtual void OnCompleteInitializePhoneApplication(NavigationEventArgs e) { }

		protected virtual void OnRootFrameNavigationFailed(NavigationFailedEventArgs e)
		{
			if (this.IsErrorAlertEnabled)
			{
				MessageBox.Show(e.Exception.Message);
			}

			if (Debugger.IsAttached)
			{
				Debugger.Break();
			}
		}

		#endregion

		/// <summary>
		/// Gets an attribute from the Windows Phone App Manifest App element
		/// </summary>
		/// <param name="attributeName">the attribute name</param>
		/// <returns>the attribute value</returns>
		private static string GetAppAttribute(string attributeName)
		{
			string appManifestName = "WMAppManifest.xml";
			string appNodeName = "App";

			var settings = new XmlReaderSettings();
			settings.XmlResolver = new XmlXapResolver();

			using (XmlReader rdr = XmlReader.Create(appManifestName, settings))
			{
				rdr.ReadToDescendant(appNodeName);

				if (!rdr.IsStartElement())
				{
					throw new System.FormatException(appManifestName + " is missing " + appNodeName);
				}

				return rdr.GetAttribute(attributeName);
			}
		}
	}
}
